/**
 * @file		constParams.cpp
 * @description		This sample demonstrates the use of constant
 *			parameters. This is a form of error checking.
 *			The compiler checks to make sure you don't modify
 *			a const parameter. The modifier in front of the parameter
 *			also notifies programmers that the parameter should
 *			not be modified.
 * @course		CSCI 123 Section 00000
 * @assignment 
 * @date		mm/dd/yyyy
 * @author		Brad Rippe (00000000) brippe@fullcoll.edu
 * @version		5.0
 */
#include <iostream>
#include <string>
using namespace std;

/**
 * This is the bike class. The public members and functions
 * are accessible to every. The private members and functions
 * are only accessible to the class. This example doesn't use
 * a constructor to create the Bike Object. In this case, C++
 * will provide one for us that does NOTHING.
 */
class Bike {
public:

	/**
	 * I'm a FRIEND!!!!
	 * I'm not a member function only a friend!
	 * Compares two bikes to see if their internal data is the 
	 * same. If so, we consider them to be the same bike.
	 * @param aBike1 the first bike
	 * @param aBike2 the second bike
	 * @return true if the two bikes are equal, otherwise false
	 */
	friend bool equals(const Bike& aBike1, const Bike& aBike2);
	
	/**
	 * This is the default constructor. This constructor
	 * creates a Bike object without specifying any parameters
	 */
	Bike();

	/**
	 * Creates a Bike.
	 * @param aName  sets the bike's name
	 * @param aSize sets the bike's frame size
	 * @param aDiameter sets the bike's wheel diameter
	 */
	Bike(const string& aName, int aSize, double aDiameter);

	/**
	 * Gets the bike's name.
	 * @return the name of the bike
	 */
	string getName();

	/**
	 * Set the bike's name.
	 * @param aName the name to set the bike's name to.
	 */
	void setName(const string& aName);

	/**
	 * Gets the bike's name.
	 * @return the name of the bike
	 */
	int getSize();

	/**
	 * Set the bike's frame size.
	 * @param aSize the size to set the bike's frame to.
	 */
	void setSize(int aSize);

	/**
	 * Gets the bike's name.
	 * @return the name of the bike
	 */
	double getWheelDiameter();

	/**
	 * Set the bike's wheel diameter
	 * @param aDiameter the diameter to set the bike's diameter to.
	 */
	void setWheelDiameter(double aDiameter);

private:
	// this is a private function, only this class can access
	// a private function. Private functions are usually utility
	// functions for the class. They won't be accessed by others
	// therefore the documentation can be left out. We only want to
	// expose the api that others can use.
	bool validSize(int aSize);
	string mName;
	int mSize;
	double mWheelDiameter;
};

/**
 * @return zero if the application executes successfully
 */
int main() {

	Bike mtnBike;
	mtnBike.setName("Foes");		// users have to use accessors
	mtnBike.setSize(18);			// and mutators to get to the 
	mtnBike.setWheelDiameter(26.0);		// private data in the object

	Bike mtnBike2;					// let the default constructor 
									// set values of Bike 2

	cout << "Is mtnBike1 equal to mtnBike2?\n";
	cout << "equals(mtnBike, mtnBike2) = ";
	if(equals(mtnBike, mtnBike2))
		cout << "true\n" << endl;
	else
		cout << "false\n" << endl;

	return 0;
}

// Notice that I've removed the Object Qualifier Bike::
// the equals function no longer belongs to the bike class
// friend functions can't be member functions
// Since that is now the case, we have to pass two bike objects
// to the function to compare member variables 
bool equals(const Bike& aBike1, const Bike& aBike2) {
    /* The code from the previous example is invalid here 
	   because of the const modifier
	 */

	if(aBike1.mName != aBike2.mName ||
		aBike1.mSize != aBike2.mSize ||
		aBike1.mWheelDiameter != aBike2.mWheelDiameter) {
			return false;
	}
	return true;
}

// Default Constructor
Bike::Bike() : mName("Unknown Name"), mSize(10), mWheelDiameter(12.0) {
	/* empty */
}

Bike::Bike(const string& aName, int aSize, double aDiameter) :
		   mName(aName), mSize(aSize), mWheelDiameter(aDiameter) {
	if(aName == "")
		mName = "Unknown Name";
	if(validSize(aSize))
		mSize = 10;
	if(aDiameter <= 4)
		mWheelDiameter = 5.0;
}

string Bike::getName() {
	return mName;
}

void Bike::setName(const string& aName) {
	mName = aName;
}

int Bike::getSize() {
	return mSize;
}

void Bike::setSize(int aSize) {
	if(!validSize(aSize))
		mSize = aSize;
	else
		mSize = 10;
}

double Bike::getWheelDiameter() {
	return mWheelDiameter;
}

void Bike::setWheelDiameter(double aDiameter) {
	mWheelDiameter = aDiameter;
}

bool Bike::validSize(int aSize) {
	return (aSize >= 10);
}

